﻿using System;
using Game.Objects;

namespace Game.Command
{
    public abstract class ScheduledCommand
    {
        static int _ScheduledCommandCount;

        public event EventHandler<ScheduledCommandEventArgs> Running;
        public event EventHandler<ScheduledCommandEventArgs> Canceled;
        public event EventHandler<ScheduledCommandEventArgs> Scheduled;

        readonly int _TurnsNeeded;
        readonly int _ScheduledCommandIndex;
        readonly GameBuilding _GameBuilding;

        int _TurnsCompleted;
        bool _IsCanceled;
        bool _IsRunning;

        protected ScheduledCommand(
            int turnsNeeded,
            GameBuilding gameBuilding)
        {
            _ScheduledCommandIndex = ++_ScheduledCommandCount;
            _TurnsNeeded = turnsNeeded;
            _GameBuilding = gameBuilding;
        }

        public abstract void Execute();

        public abstract string Name
        {
            get;
        }

        public GameBuilding GameBuilding
        {
            get { return _GameBuilding; }
        }

        public bool IsRunning
        {
            get { return _IsRunning; }
        }

        public abstract SchedulerCommand SchedulerCommand
        {
            get;
        }

        public int TurnsNeeded
        {
            get { return _TurnsNeeded; }
        }

        public int TurnsCompleted
        {
            get { return _TurnsCompleted; }
        }

        public int Index
        {
            get { return _ScheduledCommandIndex; }
        }

        public void Schedule(CommandExecutor commandExecutor)
        {
            _IsRunning = true;
            FireScheduled(commandExecutor);
        }

        public virtual void Cancel(CommandExecutor commandExecutor)
        {
            _IsCanceled = true;
            _IsRunning = false;
            FireCanceled(commandExecutor);
        }

        public void IncrementTurnsCompleted(CommandExecutor commandExecutor)
        {
            if (_IsCanceled)
            {
                return;
            }

            _TurnsCompleted++;
            if (_TurnsCompleted >= _TurnsNeeded)
            {
                _IsRunning = false;
                FireRunning(commandExecutor);

                Execute();
            }
        }

        protected void FireRunning(CommandExecutor commandExecutor)
        {
            var args = new ScheduledCommandEventArgs(this, commandExecutor);
            if (Running != null)
            {
                Running(this, args);
            }
        }

        protected void FireCanceled(CommandExecutor commandExecutor)
        {
            var args = new ScheduledCommandEventArgs(this, commandExecutor);
            if (Canceled != null)
            {
                Canceled(this, args);
            }
        }

        protected void FireScheduled(CommandExecutor commandExecutor)
        {
            var args = new ScheduledCommandEventArgs(this, commandExecutor);
            if (Scheduled != null)
            {
                Scheduled(this, args);
            }
        }

    }

    public class ScheduledCommandEventArgs : EventArgs
    {
        readonly ScheduledCommand _GameCommand;
        readonly CommandExecutor _CommandExecutor;

        public ScheduledCommandEventArgs(
            ScheduledCommand gameCommand,
            CommandExecutor commandExecutor)
        {
            _GameCommand = gameCommand;
            _CommandExecutor = commandExecutor;
        }

        public ScheduledCommand GameCommand
        {
            get { return _GameCommand; }
        }

        public CommandExecutor CommandExecutor
        {
            get { return _CommandExecutor; }
        }
    }

}
